
#ifndef incl_femSolids_CLASS_h
#define incl_femSolids_CLASS_h
#define EIGEN_SUPERLU_SUPPORT

#include "util.h"
#include "GeomDataLagrange.h"
#include "SolutionDataSolid.h"
#include "headersVTK.h"
#include "ElementBase.h"
#include "MaterialBase.h"
#include "SolverPetsc.h"
#include "Domain.h"
#include "ElementTypeData.h"
#include "headersBasic.h"
#include <math.h>
#include "parmetis.h"
#include <unordered_set>
#include "log.h"

#define ELE_LOC_LIMIT 536870912

#ifndef FEM_MAX_MPI_NUM
#define FEM_MAX_MPI_NUM 512
#endif

#define MPI_SEND_ELE_NUM 0xfff0
#define MPI_RECV_ELE_NUM 0xfff0
#define MPI_SEND_ELE     0xfff1
#define MPI_RECV_ELE     0xfff1
#define MPI_ELE_JOIN_NUM 0xfff2
#define MPI_ELE_JOIN     0xfff3
#define MPI_ELE_MAXCOUNT 0xfff4
#define MPI_NODE_MAP_BG  0xfff5
#define MPI_NODE_MAP_ED  0xfff6

#define MAT_SYNC_COUNT   100000

enum COMMON_ERR_CODE {
    COMMON_SUCCESS  = 0x0000,
    NO_READ_FILE_OP = 0xffff,
    OUT_OF_MEMORY   = 0x0001,
    READ_ELE_LESS   = 0x0002,
    READ_NODE_ERR   = 0x0003,
};

using std::vector;
using std::cout;
using std::string;
using std::ofstream;
using std::map;
using std::unordered_set;

class ElementBase;



class femSolids
{
    private:
    //public:

        string    infilename, dirname, jobname;

        int  ndim, ndof;
        int  num;
        int  numTRIA3, numTRIA6, numQUAD4, numQUAD8, numQUAD9;
        int  numTETRA4, numPYRAM5, numWEDGE6, numHEXA8, numTETRA10, numPYRAM13, numPYRAM14, numWEDGE15, numWEDGE18, numHEXA20, numHEXA27;
        int num_nodeInLocalElem;
        int num_nodeInLocalElem2;
        int  stepsMax, iterationsMax, outputFreq, fileCount;
        int  nNode_global, nNode_local, nNode_owned;
        int  node_start, node_end, elem_start, elem_end;
        int  row_start, row_end, ntotdofs_local, ntotdofs_global;
              
        int  dispDOF, presDOF, totalDOF;
        int  numMaterials;
        int  numElemTypes;
        int  numNodalForces;
        int  numSPCs;
        int  outputfrequency;

        SolverType   NONLINEAR_SOLVER_TYPE;
        int  AlgoType, SCHEME_TYPE;

        bool  solverOK, firstIteration, loadStepConverged;
        bool  localStiffnessError, intVarFlag, IMPLICIT_SOLVER, MIXED_ELEMENT;
        bool  ARC_LENGTH, convergedFlagPrev, convergedFlag;

        double  arclenIncr, arclenIncrPrev, arclenIncrMax, arclenIncrMin;
        double  loadFactor, loadFactorPrev, loadFactorPrev2;


        vector<NodalBC>      NodalBCs;
        vector<NodalForce>   NodalForces;
        vector<string>   outputlist_nodal,  outputlist_elemental;

        VectorXd  solnIncrStep, solnIncrIter;

        vector<double>  loadfactorVec;
        vector<vector<double> >  OutputData, nodeForcesData;

        ElementBase  **elems;

        SolutionDataSolid  SolnData;
        GeomDataLagrange  GeomData;

        PetscErrorCode  errpetsc;
        PetscLogDouble  mem_usage;

        double    computerTimeAssembly, computerTimeSolver, computerTimePostprocess, computerTimePattern, computerTimeTimeLoop;
        double    conv_tol, timeFinal, rhsNorm, rhsNormPrev;

        VectorXd  td, reacVec;

        vector<int>              assyForSoln, dofs_specified, dofs_specified_pres;
        vector<int>              node_map_get_old, node_map_get_new;
        vector<int>              node_map_get_old1;
        vector<vector<int> >     node_elem_conn;
        vector<vector<int> >     NodeDofArray, globalDOFnumsAll;
        vector<vector<PetscInt> > forAssyVecAll;
        vector<vector<bool> >    NodeType;
        vector<vector<int> >     midnodeData;

        // std::map<int, int> node_map_g2l;
        // vector<int> node_map_l2g;
        vector<myPoint>  nodePosDataLocal;
        //wj
        vector<int>  nodeInLocalElem;
        int num1;
        std::vector<int>  displs;
        std::vector<int>  nNode_owned_vector;
        std::vector<double> local_points;
        std::vector<double> all_points;    
        
        vector<ElementTypeData*>  ElementTypeDataList;
        vector<MaterialBase*>    MatlDataList;

        unique_ptr<SolverPetsc>  solverPetsc;

        // read file
        string input_file_name;

        int n_mpi_procs, this_mpi_proc;
    
        int ele_local_size;
        int nElem_global, nElem_local, nElem_start, nElem_end, nElem_local_max;

        vector<vector<int> > elemConn;
        vector<int> elemConn_idx;

        /// Partitioning Array
        idx_t *part;

        /// Index of local elements
        unordered_set<int> ele_local_idx_set;

        vector<int> ele_idx_map;

    public:
        std::map<int, int> node_map_g2l;
        vector<int> node_map_l2g;
        std::map<int, int> node_map_o2n;
        std::map<int, int> node_map_n2o;        
        femSolids(string& input_file);

        ~femSolids();

        ///////////////////////////////////////////////////////////
        //
        // PRE-PROCESSOR PHASE member functions
        //
        ///////////////////////////////////////////////////////////
        
        void  setJobName(string& jname)
        {
            jobname = jname;
            return;
        }

        // read file
        int  readInputData(string& fname);

        COMMON_ERR_CODE read_file_op(ifstream& infile, string& op_type);

        COMMON_ERR_CODE readCommonInfo(ifstream& infile);

        COMMON_ERR_CODE readSolidElements(ifstream& infile);

        COMMON_ERR_CODE readSolidElementsLocal(ifstream& infile);

        COMMON_ERR_CODE readSolidNodesLocal(ifstream& infile);
        COMMON_ERR_CODE readSolidNodesLocal2(ifstream& infile);
        COMMON_ERR_CODE readSolidNodesLocal3(ifstream& infile);
        COMMON_ERR_CODE prepareInputData();

        PetscErrorCode splitSolidElements();

        PetscErrorCode recvLocalElements();

        int  readInputBDF(ifstream& infile);

        int  readConfiguration(string& fname);

        int  readModelType(ifstream& infile, string& line);

        int  readNodes(ifstream& infile, string& line);

        //wj
        int  readNodes1(ifstream& infile, string& line);
        COMMON_ERR_CODE read_file_op1(ifstream& infile, string& op_type);
        COMMON_ERR_CODE readCommonInfo1(ifstream& infile);
        COMMON_ERR_CODE readCommonInfo3(ifstream& infile);
        COMMON_ERR_CODE readCommonInfo4(ifstream& infile);
        COMMON_ERR_CODE read_file_op2(ifstream& infile, string& op_type);
        COMMON_ERR_CODE readCommonInfo2(ifstream& infile);
        COMMON_ERR_CODE read_file_op3(ifstream& infile, string& op_type);


        int  readNodesLocal(ifstream& infile, string& line);       
        int  readNodesLocal1(ifstream& infile, string& line); 
        int  readNodesLocal2(ifstream& infile, string& line); 

        int  readSurfaceElements(ifstream& infile, string& line);

        int  readPrescribedBCs(ifstream& infile, string& line);

        int  readNodalForces(ifstream& infile, string& line);

        int  readBodyForce(ifstream& infile, string& line);

        int  readInitialConditions(ifstream& infile, string& line);

        int  readSolverDetails(ifstream& infile, string& line);

        int  readSolverDetails(string& fname);

        int  readTimeFunctions(ifstream& infile, string& line);

        int  deallocatePetscObjects();

        int  readElementProps(ifstream& infile, string& line);

        int  readMaterialProps(ifstream& infile, string& line);

        int  readOutputDetails(ifstream& infile, string& line);

        int  readNodalDataForOutput(ifstream& infile, string& line);

        int  printInfo();

        int  plotGeom(int, bool, int, bool, int*);

        int  applyExternalForces();

        int  writeNodalData();

        int  writeReadResult(int, string&);

        int  prepareDataForMixedElements();

        ///////////////////////////////////////////////////////////
        //
        // SOLUTION PHASE member functions
        //
        ///////////////////////////////////////////////////////////

        int  solveWithNewtonRaphson();

        int  solveWithArclength();

        int  setSolver(int);

        int  prepareMatrixPattern();

        int  setSolverDataForFullyImplicit();

        bool converged();

        bool diverging(double);

        int  timeUpdate();

        int  updateIterStep();

        int  reset();

        int  saveSolution();

        int  addExternalForces();

        int  addBoundaryConditions();

        int  setSpecifiedDOFs(vector<vector<bool> >& NodeType);

        int  setBoundaryConditions();

        int  setInitialConditions();

        int  solveFullyImplicit();

        int  calcStiffnessAndResidual();

        int  factoriseSolveAndUpdate();

        int  copyElemInternalVariables();

        int  calcMassMatrixForExplicitDynamics();

        int  ModalAnalysis(int nn=10, bool flag=true, double fact=1.0);

        ///////////////////////////////////////////////////////////
        //
        // POST-PROCESSOR PHASE member functions
        //
        ///////////////////////////////////////////////////////////

        int  postProcess();

        int  projectStrains(bool, int, int, int);

        int  projectStresses(bool, int, int, int);

        int  projectInternalVariables(bool, int, int, int);

        int  computeElementErrors(int);
};




extern femSolids* globalFemSolidsInstance; // 声明全局变量

#endif






